﻿using Neoit.Utils.DataModel;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Neoit.Utils.Extensions
{
    /// <summary>
    /// StringExtension-复杂型
    /// </summary>
    public static partial class StringExtension
    {

        #region Json
        /// <summary>
        /// 实体或者匿名对象转json字符串-CamelCase(小驼峰)
        /// NameValue - nameValue
        /// </summary>
        /// <param name="obj">实体对象</param>
        /// <param name="setting">json序列化配置</param>
        /// <returns></returns>
        public static string ToJson<T>(this T obj, JsonSerializerSettings setting = null)
        {
            if (obj == null) return "";
            if (setting == null)
            {
                setting = new JsonSerializerSettings
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,//忽略循环引用
                    DateFormatString = "yyyy/MM/dd HH:mm:ss", //否则为默认形式："2022-12-18T13:26:04.0227883+08:00"
                    ContractResolver = new CamelCasePropertyNamesContractResolver()
                };
            }
            return JsonConvert.SerializeObject(obj, setting);
        }
        /// <summary>
        /// 实体或者匿名对象转json字符串-原格式
        /// NameValue - NameValue
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="setting"></param>
        /// <returns></returns>
        public static string ToJsonWithOriginal<T>(this T obj, JsonSerializerSettings setting = null)
        {
            if (obj == null) return "";
            if (setting == null)
            {
                setting = new JsonSerializerSettings
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,//忽略循环引用
                    DateFormatString = "yyyy/MM/dd HH:mm:ss", //否则为默认形式："2022-12-18T13:26:04.0227883+08:00"
                };
            }
            return JsonConvert.SerializeObject(obj, setting);
        }
        /// <summary>
        /// json字符串转实体类
        /// </summary>
        public static T ToEntity<T>(this string str)
        {
            if (Regex.IsMatch(str, @"^\[.*\]$")) //数组
            {
                return JArray.Parse(str).ToObject<T>();
            }
            else //实体类
            {
                return JObject.Parse(str).ToObject<T>();
            }
        }
        /// <summary>
        /// 获取json字符串中的属性值
        /// </summary>
        /// <param name="str">json字符串</param>
        /// <param name="key">"res.data.name"、"res[1].data.name[1][1]"、"[1][2].name[1]</param>
        /// <returns></returns>
        public static string JsonValue(this string str, string key)
        {
            if (string.IsNullOrWhiteSpace(str) || string.IsNullOrWhiteSpace(key)) return null;
            var listKey = Regex.Matches(key, @"(\[\d+\])|(\w+)").ToList();
            var isArray = str.IndexOf('[') == 0;
            var obj = isArray ? JArray.Parse(str) : JObject.Parse(str) as JToken;
            foreach (var item in listKey)
            {
                if (item.ToString().IndexOf('[') == 0)//find in JArray
                {
                    var index = Convert.ToInt32(Regex.Match(item.ToString(), @"\d+").Value);
                    if (index >= obj.Count()) return null;
                    obj = obj[index];
                }
                else//find in JObject
                {
                    if (!(obj is JObject)) return null;
                    obj = obj[item.Value];
                }
            }
            return Convert.ToString(obj);
        }
        /// <summary>
        /// json字符串转dynamic
        /// </summary>
        /// <param name="jsonString"></param>
        /// <returns></returns>
        public static dynamic Dynamic(this string jsonString)
        {
            if (string.IsNullOrWhiteSpace(jsonString)) return null;
            return JsonConvert.DeserializeObject<dynamic>(jsonString);
        }
        #endregion

    }
}
